<?php


namespace App\Services;

use App\Models\Order;
use App\Models\RolePermission;
use Swoole\Http\Request;
use Swoole\WebSocket\Frame;
use Swoole\WebSocket\Server;
use Illuminate\Support\Facades\Redis;
use Hhxsv5\LaravelS\Swoole\WebSocketHandlerInterface;

class WebSocketService implements WebSocketHandlerInterface
{
    // 声明没有参数的构造函数
    public function __construct()
    {

    }
    public function onOpen(Server $server, Request $request)
    {
        //根据前后端 映射不同的分组
        $requestData = request()->input();
        if($requestData['type'] == 'admin'){
            // 将用户映射放入一张hash表
            Redis::hset('ws:admin_table','admin_id_'.auth('admin')->id(),$request->fd);
            Redis::hset('ws:admin_table','admin_fd_'.$request->fd,auth('admin')->id());

            // 在集合中 存入管理员组的集合
            Redis::sadd('ws:admin_group', $request->fd);
        }else if($requestData['type'] == 'user'){
            // 将用户映射放入一张hash表
            Redis::hset('ws:admin_user','user_id_'.auth('admin')->id(),$request->fd);
            Redis::hset('ws:admin_user','user_fd_'.$request->fd,auth('admin')->id());
        }

        // 在触发onOpen事件之前，建立WebSocket的HTTP请求已经经过了Laravel的路由，
        // 所以Laravel的Request、Auth等信息是可读的，Session是可读写的，但仅限在onOpen事件中。
        \Log::info('New WebSocket connection', [$request->fd, request()->input(), session()->getId(), session('xxx'), session(['yyy' => time()])]);

        //建立链接时的提示
        $server->push($request->fd, json_encode(['type'=>'on_open','data'=>$request->fd]));
        // throw new \Exception('an exception');// 此时抛出的异常上层会忽略，并记录到Swoole日志，需要开发者try/catch捕获处理
    }

    public function onMessage(Server $server, Frame $frame)
    {
        $requestData = json_decode($frame->data,true);

        switch ($requestData['type']) {
        	case 'ping':
                $server->push($frame->fd,json_encode(['type'=>'pong_' . $frame->fd]));
        		break;
            case 'admin_init':
                //群发上线信息
                $this->countOnlineAdmins($server);
                //统计订单信息
                $this->countNewOrder($server);

//                \Log::info('Received message', [$frame->fd, $frame->data, $frame->opcode, $frame->finish]);
//                $server->push($frame->fd,json_encode(['type'=>'init','msg'=>'is_ok']));
                break;
        	default:
        		# code...
        		break;
        }

//        $server->push($frame->fd, date('Y-m-d H:i:s'));
        // throw new \Exception('an exception');// 此时抛出的异常上层会忽略，并记录到Swoole日志，需要开发者try/catch捕获处理
    }
    public function onClose(Server $server, $fd, $reactorId)
    {
        $server->push($fd, date('Y-m-d H:i:s') . '断开连接');
         \Log::info('Received message', [$fd, $reactorId]);
        // throw new \Exception('an exception');// 此时抛出的异常上层会忽略，并记录到Swoole日志，需要开发者try/catch捕获处理

        //判断是否在集合里面
        if(Redis::sismember('ws:admin_group',$fd)){
            $admin_id = Redis::hget('ws:admin_table','admin_fd_'.$fd);

            Redis::hdel('ws:admin_table','admin_fd_'.$fd);
            Redis::hdel('ws:admin_table','admin_id_'.$admin_id);

            //移出group
            Redis::srem('ws:admin_group',$fd);

            $this->countOnlineAdmins($server);
        }else{
            Redis::hdel('ws:user_table','user_fd_'.$fd);
            Redis::hdel('ws:user_table','user_id_'.$reactorId);
        }


        //

    }

    /**
     * 统计在线管理员
     * User: Clannad ~ ☆
     * @param $server
     */
    public function countOnlineAdmins($server)
    {
        //群发上线信息
        $online_admins = Redis::smembers('ws:admin_group');

        $count = count($online_admins);

        foreach ($online_admins as $k => $v) {
            $server->push($v,json_encode(['type'=>'online_admins','num'=>$count]));
        }
    }

    /**
     * 统计未发订单
     * User: Clannad ~ ☆
     * @param $server
     */
    public function countNewOrder($server)
    {
        $online_admins = Redis::smembers('ws:admin_group');
        $orders = Order::query()->where(['status'=>1])->count('id');

        foreach ($online_admins as $k => $v) {
            //查用户id
            $admin_id = Redis::hget('ws:admin_table','admin_fd_'.$v);

            $permissions = RolePermission::query()->whereIn('role_id',function ($query) use ($admin_id){
                $query->from('admin_role')->select('role_id')->where('admin_id',$admin_id)->get();
            })->get()->pluck('permission_id')->toArray();

            \Log::info('管理权限：' . $admin_id,$permissions);

            if(in_array('57',$permissions) || $admin_id == 1){
                $server->push($v,json_encode(['type'=>'order_count','num'=>$orders]));
            }
        }

    }
}
